import Axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios";
import qs from "qs";
import message from "@/utils/message";

const downFileUrl: string[] = [
	"/admin/appointment/export",
	"/file/excel/user_import.xls",
];

type Response = {
	data?: any;
	code?: number;
	msg?: string;
	prompt?: string;
};

const myUrl = import.meta.env.VITE_BASE_URL

class Http {
	private server;

	constructor(url: string, timeout = 5000) {
		this.server = Axios.create({
			baseURL: url,
			timeout,
		});
		this.userInterceptRequest();
		this.userInterceptResponse();
	}

	private userInterceptRequest() {
		this.server.interceptors.request.use(
			(config: AxiosRequestConfig) => {
				const token = localStorage.getItem('token');
				const newConfig = config;
				if (token) {
					newConfig.headers = {
						Authorization: `Bearer ${token}`,
					};
				}
				return newConfig;
			},
			(error: AxiosError) => error
		);
	}

	private userInterceptResponse() {
		this.server.interceptors.response.use((result: AxiosResponse<Response>): Promise<Response> =>
			new Promise((resolve) => {
				// console.log(resolve);
				let data = result.data;
				if (downFileUrl.includes(result.config.url as string)) {
					data = {
						code: 0,
						data: result.data,
					};
				}
				resolve(data);
			}),
			(error: AxiosError) => {
				if (Axios.isCancel(error)) {
					return { code: 416 };
				}
				return error.response?.data;
				// console.log(error);
			}
		);
	}

	public async get<T>(url: string, params?: T, isShowMessage?: boolean) {
		const param = qs.stringify(params);
		const result = await this.server.get(`${url}?${param}`);
		return this.handleResultDispose(result, isShowMessage);
	}

	public async post<T, U>(
		url: any,
		data?: T,
		params?: U,
		isShowMessage?: boolean
	) {
		const result = await this.server.post(url, data, { params });
		return this.handleResultDispose(result, isShowMessage);
	}

	public async put<T, U>(
		url: any,
		data?: T,
		params?: U,
		isShowMessage?: boolean
	) {
		const result = await this.server.put(url, data, { params });
		return this.handleResultDispose(result, isShowMessage);
	}

	// public async delete<T>(url: string, params?: T, isShowMessage?: boolean) {
	// 	const result = await this.server.delete(url, { params });
	// 	return this.handleResultDispose(result, isShowMessage);
	// }
	
	public async post2<T>(
		url: any,
		data?: T,
		params?: U,
		isShowMessage?: boolean
	) {
		const param = qs.stringify(data);
		const result = await this.server.post(`${url}?${param}`);
		return this.handleResultDispose(result, isShowMessage);
	}

	public async downLoad<T>(url: string, param?: T | undefined) {
		downFileUrl.push(url);
		const result = await this.server.get(url, {
			params: param,
			responseType: "blob",
		});
		return this.handleResultDispose(result);
	}

	public async upLoad<T>(url: string, data?: T | undefined, params?: T) {
		const result = await this.server.post(url, data, {
			params: params,
			responseType: 'blob'
		});
		return result;
	}

	private handleResultDispose(data: any, isShowMessage?: boolean): any {
		const result = data;
		if (!result) return undefined;
		if (result.code === '2000') {
			if (isShowMessage && result.prompt) {
				message.success(result.prompt);
			}
			if (result.data) {
				return result.data;
			}
			return {};
		} else if (result.code === 10) {
			if ((result.data && Object.prototype.toString.call(result.data) === '[object Object]') || (result.data && result.data.length > 0)) {
				message.error('数据有误，请进行修改');
				return { data: result.data };
			} else {
				if (data.code) {
					return this.handleError(data.code, result.prompt || "发生不知名错误");
				}
			}
		} else if (result.code == 200) {
			message.success(result.message);
			if (result) {
				return result.data;
			}
			return {};
		} else if (result.code == 201) {
			message.error(result.message || "发生不知名错误");
			return undefined;
		}
		else if (data.code) {
			return this.handleError(data.code, result.msg || "发生不知名错误");
		}
		message?.error("发生错误");
		return undefined;
	}

	private handleError(statusCode: number, msg: string): undefined | void {
		const obj: Record<number, () => void> = {
			'4010': () => {
				message.error(msg);
				window.localStorage.clear();
				window.location.replace("/login");
				return undefined;
			},
			416: () => {
				message.warning("请勿频繁请求");
			},
			500: () => {
				message.error('系统错误');
				return undefined;
			},
		};
		if (obj[statusCode]) {
			return obj[statusCode]();
		}
		message.error(msg);
		return undefined;;		
	}
}

export default new Http(myUrl as string);

// process.env.VUE_APP_BASE_URL as string